//package org.learn.develop.utils.spi;
//
//
//import org.learn.develop.common.annotations.extension.Adaptive;
//import org.learn.develop.common.annotations.extension.spi;
//import org.learn.develop.utils.*;
//
//import java.io.BufferedReader;
//import java.io.InputStreamReader;
//import java.lang.reflect.Method;
//import java.nio.charset.StandardCharsets;
//import java.util.Arrays;
//import java.util.Enumeration;
//import java.util.HashMap;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.concurrent.ConcurrentMap;
//import java.util.regex.Pattern;
//
//
//public class ExtensionLoader<T> {
//
//
//    private static final String SERVICES_DIRECTORY = "META-INF/services/";
//    private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
//
//
//    private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
//    private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();
//
//    // ==============================
//
//    private final Class<?> type;
//
//    private final ExtensionFactory objectFactory = new SpiExtensionFactory();
////    private final ExtensionFactory objectFactory;
//
//    private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
//    private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
//
//
//    private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
//    private final Holder<Object> cachedAdaptiveInstance = new Holder<>();
//    private volatile Class<?> cachedAdaptiveClass = null;
//    private String cachedDefaultName;
//    private volatile Throwable createAdaptiveInstanceError;
//
//
//    private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();
//
//    private ExtensionLoader(Class<?> type) {
//        this.type = type;
////        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
//    }
//    private static <T> boolean withExtensionAnnotation(Class<T> type) { return type.isAnnotationPresent(spi.class); }
//
//    /********************************************************************************************************************
//     * Api Method
//    ********************************************************************************************************************/
//    public static <T>T getSpiClassInstance(Class<T> type){
//        return getExtensionLoader(type).getAdaptiveExtension();
//    }
//
//    @SuppressWarnings("unchecked")
//    public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
//        if (type == null) {
//            throw new IllegalArgumentException("Extension type == null");
//        }
//        if (!type.isInterface()) {
//            throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
//        }
//        if (!withExtensionAnnotation(type)) {
//            throw new IllegalArgumentException("Extension type (" + type +
//                    ") is not an extension, because it is NOT annotated with @" + spi.class.getSimpleName() + "!");
//        }
//
//        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
//        if (loader == null) {
//            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
//            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
//        }
//        return loader;
//    }
//
//    @SuppressWarnings("unchecked")
//    public T getAdaptiveExtension() {
//        Object instance = cachedAdaptiveInstance.get();
//        if (instance == null) {
//            if (createAdaptiveInstanceError == null) {
//                synchronized (cachedAdaptiveInstance) {
//                    instance = cachedAdaptiveInstance.get();
//                    if (instance == null) {
//                        try {
//                            instance = createAdaptiveExtension();
//                            cachedAdaptiveInstance.set(instance);
//                        } catch (Throwable t) {
//                            createAdaptiveInstanceError = t;
//                            throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
//                        }
//                    }
//                }
//            } else {
//                throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
//            }
//        }
//
//        return (T) instance;
//    }
//
//
//
//
//    /********************************************************************************************************************
//     * 创建SPI 适配实例
//    ********************************************************************************************************************/
//
//    @SuppressWarnings("unchecked")
//    private T createAdaptiveExtension() {
//        try {
//            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
//        } catch (Exception e) {
//            throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
//        }
//    }
//
//    /**
//     * 在类上 返回类适配
//     * 在方法上 需要一些列创建
//     * @return
//     */
//    private Class<?> getAdaptiveExtensionClass() {
//        getExtensionClasses();
//        if (cachedAdaptiveClass != null) {
//            return cachedAdaptiveClass;
//        }
//        return cachedAdaptiveClass = createAdaptiveExtensionClass();
//    }
//
//
//    /********************************************************************************************************************
//     *  spi 分析是否是类上的Adapter
//    ********************************************************************************************************************/
//    private Map<String, Class<?>> getExtensionClasses() {
//        Map<String, Class<?>> classes = cachedClasses.get();
//        if (classes == null) {
//            synchronized (cachedClasses) {
//                classes = cachedClasses.get();
//                if (classes == null) {
//                    classes = loadExtensionClasses();
//                    cachedClasses.set(classes);
//                }
//            }
//        }
//        return classes;
//    }
//
//
//    /********************************************************************************************************************
//     *  File    文件扫描
//    ********************************************************************************************************************/
//    private void cacheDefaultExtensionName() {
//        final spi defaultAnnotation = type.getAnnotation(spi.class);
//        if (defaultAnnotation != null) {
//            String value = defaultAnnotation.value();
//            if ((value = value.trim()).length() > 0) {
//                String[] names = NAME_SEPARATOR.split(value);
//                if (names.length > 1) {
//                    throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
//                            + ": " + Arrays.toString(names));
//                }
//                if (names.length == 1) {
//                    cachedDefaultName = names[0];
//                }
//            }
//        }
//    }
//
//    private Map<String, Class<?>> loadExtensionClasses() {
//        cacheDefaultExtensionName();
//        Map<String, Class<?>> extensionClasses = new HashMap<>();
//        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
//        return extensionClasses;
//    }
//
//    private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) {
//        String fileName = dir + type;
//        try {
//            Enumeration<java.net.URL> urls;
//            ClassLoader classLoader = ClassLoaderUtils.getClassLoader(ExtensionLoader.class);
//            if (classLoader != null) {
//                urls = classLoader.getResources(fileName);
//            } else {
//                urls = ClassLoader.getSystemResources(fileName);
//            }
//            if (urls != null) {
//                while (urls.hasMoreElements()) {
//                    java.net.URL resourceURL = urls.nextElement();
//                    loadResource(extensionClasses, classLoader, resourceURL);
//                }
//            }
//        } catch (Throwable t) {
//            t.printStackTrace();
//        }
//    }
//
//
//
//    private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
//        try {
//            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
//                String line;
//                while ((line = reader.readLine()) != null) {
//                    final int ci = line.indexOf('#');
//                    if (ci >= 0) {
//                        line = line.substring(0, ci);
//                    }
//                    line = line.trim();
//                    if (line.length() > 0) {
//                        try {
//                            String name = null;
//                            int i = line.indexOf('=');
//                            if (i > 0) {
//                                name = line.substring(0, i).trim();
//                                line = line.substring(i + 1).trim();
//                            }
//                            if (line.length() > 0) {
//                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
//                            }
//                        } catch (Throwable t) {
//                            IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
//                            exceptions.put(line, e);
//                        }
//                    }
//                }
//            }
//        } catch (Throwable t) {
//            t.printStackTrace();
//        }
//    }
//
//
//    private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
//        if (!type.isAssignableFrom(clazz)) {
//            throw new IllegalStateException("Error occurred when loading extension class (interface: " +
//                    type + ", class line: " + clazz.getName() + "), class "
//                    + clazz.getName() + " is not subtype of interface.");
//        }
//        if (clazz.isAnnotationPresent(Adaptive.class)) {
//            cacheAdaptiveClass(clazz);
//        }  else {
//            clazz.getConstructor();
//            if (StringUtils.isEmpty(name)) {
//                name = findAnnotationName(clazz);
//                if (name.length() == 0) {
//                    throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
//                }
//            }
//
////            方法上的 adapt 需要代理
//            String[] names = NAME_SEPARATOR.split(name);
//            if (ArrayUtils.isNotEmpty(names)) {
//                for (String n : names) {
//                    cacheName(clazz, n);
//                    saveInExtensionClass(extensionClasses, clazz, name);
//                }
//            }
//        }
//    }
//
//    /**
//     * cache Adaptive class which is annotated with <code>Adaptive</code>
//     */
//    private void cacheAdaptiveClass(Class<?> clazz) {
//        if (cachedAdaptiveClass == null) {
//            cachedAdaptiveClass = clazz;
//        } else if (!cachedAdaptiveClass.equals(clazz)) {
//            throw new IllegalStateException("More than 1 adaptive class found: "
//                    + cachedAdaptiveClass.getClass().getName()
//                    + ", " + clazz.getClass().getName());
//        }
//    }
//
//
//    /**
//     * put clazz in extensionClasses
//     */
//    private void saveInExtensionClass(Map<String, Class<?>> extensionClasses, Class<?> clazz, String name) {
//        Class<?> c = extensionClasses.get(name);
//        if (c == null) {
//            extensionClasses.put(name, clazz);
//        } else if (c != clazz) {
//            throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName());
//        }
//    }
//
//    /**
//     * cache name
//     */
//    private void cacheName(Class<?> clazz, String name) {
//        if (!cachedNames.containsKey(clazz)) {
//            cachedNames.put(clazz, name);
//        }
//    }
//
//
//
//    @SuppressWarnings("deprecation")
//    private String findAnnotationName(Class<?> clazz) {
////        org.apache.dubbo.common.Extension extension = clazz.getAnnotation(org.apache.dubbo.common.Extension.class);
////        if (extension == null) {
////            String name = clazz.getSimpleName();
////            if (name.endsWith(type.getSimpleName())) {
////                name = name.substring(0, name.length() - type.getSimpleName().length());
////            }
////            return name.toLowerCase();
////        }
////        return extension.value();
//        return null;
//    }
//
//
//
//    /********************************************************************************************************************
//     *  解析SPI类的 adaptive  方法代理 实现
//     ********************************************************************************************************************/
//    private Class<?> createAdaptiveExtensionClass() {
////        String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
////        ClassLoader classLoader = findClassLoader();
////        org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
////        return compiler.compile(code, classLoader);
//        return null;
//    }
//
//    /********************************************************************************************************************
//     *  实例化的SPI 类进行后处理  代理等等
//    ********************************************************************************************************************/
//    private T injectExtension(T instance) {
//        try {
//            if (objectFactory != null) {
//                for (Method method : instance.getClass().getMethods()) {
//                    if (MethodUtils.isSetter(method)) {
//                        Class<?> pt = method.getParameterTypes()[0];
////                        基本类型不做处理
//                        if (ReflectUtils.isPrimitives(pt)) { continue; }
//
//                        try {
//                            String property = MethodUtils.getSetterProperty(method);
//                            Object object = objectFactory.getExtension(pt, property);
//                            if (object != null) {
//                                method.invoke(instance, object);
//                            }
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return instance;
//    }
//
//
//
//
//
//    @Override
//    public String toString() {
//        return this.getClass().getName() + "[" + type.getName() + "]";
//    }
//
//}
